﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.UI;
using System.Web.UI.WebControls;
using NIGeoCoding;

[assembly: TagPrefix("NIControls", "info")]

namespace NIControls
{
  [DefaultProperty("Text")]
  [ToolboxData("<{0}:NIAddressManager runat=server></{0}:NIAddressManager>")]
  public class NIAddressManager : WebControl, IPostBackEventHandler
  {
    public event AddressSelectedHandler AddressSelected;
    public delegate void AddressSelectedHandler(object sender, NIAddressManagerArgs e);

    private Dictionary<string, string> lookups;
    private Response results;

    public NIAddressManager()
    {
      lookups = new Dictionary<string, string>();
      lookups.Add("Address0", "Address:");
      lookups.Add("City", "City:");
      lookups.Add("State", "State:");
      lookups.Add("PostalCode", "Postal Code:");
      lookups.Add("Country", "Country:");
    }

    protected override void OnInit(EventArgs e)
    {
      Page.RegisterRequiresControlState(this);
      base.OnInit(e);
    }

    protected override object SaveControlState()
    {
      return (object)this.results;
    }

    protected override void LoadControlState(object savedState)
    {
      results = (Response)savedState;
    }

    protected override void Render(HtmlTextWriter writer)
    {
      this.RenderContents(writer);
    }

    protected override void RenderContents(HtmlTextWriter output)
    {
      PostBackOptions p = new PostBackOptions(this);
      output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "1");
      output.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "1");
      output.AddAttribute(HtmlTextWriterAttribute.Border, "0");
      output.AddAttribute("style", "float: left; width: 500px;");
      output.RenderBeginTag(HtmlTextWriterTag.Table);

      foreach (KeyValuePair<string, string> kvp in lookups)
      {
        output.RenderBeginTag(HtmlTextWriterTag.Tr);
        output.RenderBeginTag(HtmlTextWriterTag.Td);
        output.Write(kvp.Value);
        output.RenderEndTag();
        output.RenderBeginTag(HtmlTextWriterTag.Td);
        output.AddAttribute(HtmlTextWriterAttribute.Type, "text");
        output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_" + kvp.Key);
        output.AddAttribute(HtmlTextWriterAttribute.Name, this.ClientID + "_" + kvp.Key);
        output.AddAttribute(HtmlTextWriterAttribute.Value, (string)ViewState[this.ClientID + "_" + kvp.Key]);
        output.RenderBeginTag(HtmlTextWriterTag.Input);
        output.RenderEndTag();
        output.RenderEndTag();
        output.RenderEndTag();
      }
      output.RenderBeginTag(HtmlTextWriterTag.Tr);
      output.RenderBeginTag(HtmlTextWriterTag.Td);
      output.AddAttribute(HtmlTextWriterAttribute.Onclick,
        Page.ClientScript.GetPostBackEventReference(this, "Search"));
      output.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
      output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_Search");
      output.AddAttribute(HtmlTextWriterAttribute.Name, this.ClientID + "_Search");
      output.AddAttribute(HtmlTextWriterAttribute.Value, "Search");
      output.RenderBeginTag(HtmlTextWriterTag.Input);
      output.RenderEndTag();
      output.RenderEndTag();

      output.RenderBeginTag(HtmlTextWriterTag.Td);
      output.AddAttribute(HtmlTextWriterAttribute.Onclick,
        Page.ClientScript.GetPostBackEventReference(this, "Save"));
      output.AddAttribute(HtmlTextWriterAttribute.Type, "submit");
      output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_Save");
      output.AddAttribute(HtmlTextWriterAttribute.Name, this.ClientID + "_Save");
      output.AddAttribute(HtmlTextWriterAttribute.Value, "Save");
      output.RenderBeginTag(HtmlTextWriterTag.Input);
      output.RenderEndTag();
      output.RenderEndTag();
      output.RenderEndTag();
      output.RenderEndTag();

      output.AddAttribute("style", "height: 300px; width: 500px; float: left;");
      output.AddAttribute(HtmlTextWriterAttribute.Id, "map_canvas");
      output.RenderBeginTag(HtmlTextWriterTag.Div);
      output.RenderEndTag();

      if (this.results != null && results.Placemark != null)
      {
        output.AddAttribute(HtmlTextWriterAttribute.Cellpadding, "1");
        output.AddAttribute(HtmlTextWriterAttribute.Cellspacing, "1");
        output.AddAttribute(HtmlTextWriterAttribute.Border, "1");
        output.AddAttribute("style", "clear:both; float:left;");
        output.RenderBeginTag(HtmlTextWriterTag.Table);

        foreach (Placemark place in results.Placemark)
        {
          output.RenderBeginTag(HtmlTextWriterTag.Tr);
          output.RenderBeginTag(HtmlTextWriterTag.Td);
          output.Write(place.address);
          output.RenderEndTag();
          output.RenderBeginTag(HtmlTextWriterTag.Td);
          output.AddAttribute(HtmlTextWriterAttribute.Onclick,
            String.Format("javascript:return initialize({0},{1},\'{2}\',\'{3}\',\'{4}\',\'{5}\',\'{6}\',\'{7}\')",
              place.Point.coordinates[1],
              place.Point.coordinates[0],
              place.StreetAddress.Replace('\'', '`'),
               place.City,
               place.State,
               place.PostalCode,
               place.Country,
               place.address.Replace('\'', '`')));
          output.AddAttribute(HtmlTextWriterAttribute.Type, "Submit");
          output.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID + "_Select");
          output.AddAttribute(HtmlTextWriterAttribute.Name, this.ClientID + "_Select");
          output.AddAttribute(HtmlTextWriterAttribute.Value, "Select");
          output.RenderBeginTag(HtmlTextWriterTag.Input);
          output.RenderEndTag();
          output.RenderEndTag();
          output.RenderEndTag();
        }
        output.RenderEndTag();
      }
    }

    protected override void OnPreRender(EventArgs e)
    {
      Page.ClientScript.RegisterClientScriptInclude("Google",
        "http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAHmOjPD3wprlM51was--_NRQ4fErWIBOC2zhLr97XQjguLHEmVhRYiCAHgnp5QOIgX0CyZHNDu0EaYA&sensor=false");

      Page.ClientScript.RegisterStartupScript(typeof(Page),
        "ControlFocus", "document.getElementById('" + this.ClientID + "_Address0').focus();", true);

      Page.ClientScript.RegisterStartupScript(typeof(Page),
        "Initialize", AttachInitializeScript(), true);
    }

    protected override object SaveViewState()
    {
      foreach (KeyValuePair<string, string> kvp in lookups)
        ViewState[this.ClientID + "_" + kvp.Key] = this.Page.Request.Form[this.ClientID + "_" + kvp.Key];
      return null;
    }

    protected string AttachInitializeScript()
    {
      return "function initialize(latitude,longitude,street," +
       "city, state, postal, country, address) " +
      "{" +
          "if (GBrowserIsCompatible()) {" +
              "var map = new GMap2(document.getElementById('map_canvas'));" +
              "map.setCenter(new GLatLng(latitude, longitude), 13);" +
              "map.addOverlay(new GMarker(new GLatLng(latitude, longitude)));" +
              "map.openInfoWindow(map.getCenter(),document.createTextNode(address));" +
              "map.setUIToDefault();" +
              "document.getElementById('" + this.ClientID + "_Address0" + "').value = street;" +
              "document.getElementById('" + this.ClientID + "_City" + "').value = city;" +
              "document.getElementById('" + this.ClientID + "_State" + "').value = state;" +
              "document.getElementById('" + this.ClientID + "_PostalCode" + "').value = postal;" +
              "document.getElementById('" + this.ClientID + "_Country" + "').value = country;" +
          "}" +
         " return false;" +
        "}";
    }

    protected void OnAddressSelected(Address address)
    {
      if (AddressSelected != null)
      {
        AddressSelected(this, new NIAddressManagerArgs(address));
      }
    }

    #region IPostBackEventHandler Members

    public void RaisePostBackEvent(string eventArgument)
    {
      switch (eventArgument)
      {
        case "Search":
          string results = string.Empty;
          foreach (KeyValuePair<string, string> kvp in lookups)
            results += this.Page.Request.Form[this.ClientID + "_" + kvp.Key];
          this.results = GeoCoder.GeoCode(results);
          break;
        case "Save":
          OnAddressSelected(new Address()
          {
            StreetAddress = this.Page.Request.Form[this.ClientID + "_Address0"],
            City = this.Page.Request.Form[this.ClientID + "_City"],
            State = this.Page.Request.Form[this.ClientID + "_State"],
            PostalCode = this.Page.Request.Form[this.ClientID + "_PostalCode"],
            Country = this.Page.Request.Form[this.ClientID + "_Country"]
          });
          break;
        default:
          break;
      }
    }

    #endregion
  }
}
